package com.jichangxiu.framework.utils;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.toolkit.LambdaUtils;
import com.github.yulichang.toolkit.support.ColumnCache;
import com.github.yulichang.wrapper.segments.SelectCache;
import com.jichangxiu.common.constant.ValidateConstants;
import com.jichangxiu.common.entity.bo.ValidateBo;
import com.jichangxiu.common.entity.bo.ValidateBos;

import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.function.Function;

public class ValidateUtils {

    public static <T> void uniqueValidate(Function<QueryWrapper<T>, Long> uniqueFunction, List<ValidateBos> validBosList) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        validBosList.forEach(validBos -> fillQueryWrapper(queryWrapper, validBos));
        long count = uniqueFunction.apply(queryWrapper);
        if (count > 0L) {
            StringJoiner stringJoiner = new StringJoiner("，");
            validBosList.forEach(validBos -> validBos.getValidateBoList().forEach(validateBo -> {
                switch (validBos.getType()) {
                    case ValidateConstants.NE:
                        break;
                    case ValidateConstants.EQ:
                        stringJoiner.add("该 " + validateBo.getComment() + " 下");
                        break;
                    case ValidateConstants.OR_EQ:
                        stringJoiner.add(validateBo.getComment());
                        break;
                    case ValidateConstants.LIKE:
                        stringJoiner.add(validateBo.getComment());
                        break;
                    default:
                        break;
                }
            }));
            throw new RuntimeException("操作失败：" + stringJoiner + " 字段重复！");
        }
    }

    public static void fillQueryWrapper(QueryWrapper<?> queryWrapper, ValidateBos validBos) {
        List<ValidateBo> validateBoList = validBos.getValidateBoList();
        if (ObjectUtil.isNotEmpty(validateBoList)) {
            switch (validBos.getType()) {
                case ValidateConstants.NE:
                    validateBoList.forEach(validateBo -> queryWrapper.ne(ObjectUtil.isNotEmpty(validateBo.getValue()), validateBo.getField(), validateBo.getValue()));
                    break;
                case ValidateConstants.EQ:
                    validateBoList.forEach(validateBo -> queryWrapper.eq(ObjectUtil.isNotEmpty(validateBo.getValue()), validateBo.getField(), validateBo.getValue()));
                    break;
                case ValidateConstants.OR_EQ:
                    queryWrapper.and(wrapper -> validateBoList.forEach(validateBo -> wrapper.eq(ObjectUtil.isNotEmpty(validateBo.getValue()), validateBo.getField(), validateBo.getValue()).or()));
                    break;
                case ValidateConstants.LIKE:
                    validateBoList.forEach(validateBo -> queryWrapper.like(ObjectUtil.isNotEmpty(validateBo.getValue()), validateBo.getField(), validateBo.getValue()));
                    break;
                default:
                    break;
            }
        }
    }

    public static <T> ValidateBo createValidateBo(SFunction<T, ?> sFunction, Object value, String comment) {
        ValidateBo validateBo = new ValidateBo();
        validateBo.setField(getCache(sFunction).getColumn());
        validateBo.setValue(value);
        validateBo.setComment(comment);
        return validateBo;
    }

    public static ValidateBos createValidateBos(String type, ValidateBo... validateBoList) {
        ValidateBos validateBos = new ValidateBos();
        validateBos.setType(type);
        validateBos.setValidateBoList(ListUtil.toList(validateBoList));
        return validateBos;
    }

    public static ValidateBos createNeValidateBos(ValidateBo... validateBoList) {
        return createValidateBos(ValidateConstants.NE, validateBoList);
    }

    public static ValidateBos createOrEqValidateBos(ValidateBo... validateBoList) {
        return createValidateBos(ValidateConstants.OR_EQ, validateBoList);
    }

    public static ValidateBos createEqValidateBos(ValidateBo... validateBoList) {
        return createValidateBos(ValidateConstants.EQ, validateBoList);
    }

    private static SelectCache getCache(SFunction<?, ?> fn) {
        Class<?> aClass = LambdaUtils.getEntityClass(fn);
        Map<String, SelectCache> cacheMap = ColumnCache.getMapField(aClass);
        return cacheMap.get(LambdaUtils.getName(fn));
    }

}
